import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { ConfigService } from '@nestjs/config';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User, UserStatus } from '../entities/user.entity';
import { logAuth } from '../utils/logger';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    private configService: ConfigService,
    @InjectRepository(User)
    private userRepository: Repository<User>,
  ) {
    const jwtSecret = configService.get<string>('JWT_SECRET');
    if (!jwtSecret) {
      throw new Error('JWT_SECRET is not defined in environment variables');
    }

    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: jwtSecret,
    });
    
    logAuth('JWT策略已初始化');
  }

  async validate(payload: any) {
    // 添加调试日志，查看JWT令牌中的角色和权限信息
    logAuth('验证JWT令牌', {
      username: payload.username,
      userId: payload.sub,
      roles: payload.roles,
      permissions: payload.permissions
    });

    try {
      // 从数据库加载用户及其角色和权限
      const user = await this.userRepository.findOne({
        where: { id: payload.sub },
        relations: ['roles', 'roles.permissions'],
      });

      if (!user) {
        logAuth(`用户不存在: ${payload.username} (${payload.sub})`);
        throw new UnauthorizedException('用户不存在或已被禁用');
      }

      if (user.status !== UserStatus.ACTIVE) {
        logAuth(`用户未激活: ${user.username} (${user.id}), 状态: ${user.status}`);
        throw new UnauthorizedException('用户已被禁用');
      }

      // 确保用户对象中包含角色和权限信息
      if (!user.roles || user.roles.length === 0) {
        // 如果数据库中没有加载到角色信息，使用JWT中的角色信息
        if (payload.roles && payload.roles.length > 0) {
          logAuth(`使用JWT中的角色信息: ${user.username}`, {
            roles: payload.roles
          });
          
          // 将字符串角色转换为角色对象
          user.roles = payload.roles.map(roleName => ({ 
            name: roleName,
            code: roleName === '系统管理员' ? 'admin' : roleName.toLowerCase().replace(/\s+/g, '_'),
            permissions: []
          }));
        }
      } else {
        logAuth(`数据库中的角色信息: ${user.username}`, {
          roles: user.roles.map(r => r.name)
        });
      }

      // 直接将JWT中的权限附加到用户对象中，以供权限守卫使用
      if (payload.permissions && payload.permissions.length > 0) {
        // 将权限直接添加到用户对象，使用索引签名绕过类型检查
        (user as any).permissions = payload.permissions;
        
        // 也保留原有的_permissions属性
        user['_permissions'] = payload.permissions;
        
        logAuth(`JWT令牌中的权限信息已直接添加到用户对象: ${user.username}`, {
          permissions: payload.permissions
        });
        
        // 同时确保每个角色的权限也被正确填充
        if (user.roles && user.roles.length > 0) {
          for (const role of user.roles) {
            if (!role.permissions) {
              role.permissions = [];
            }
            
            // 将JWT中的权限信息转换为权限对象并添加到角色中
            // 仅当角色未加载权限时
            if (role.permissions.length === 0) {
              role.permissions = payload.permissions.map(code => ({
                code,
                name: code
              }));
              
              logAuth(`为角色补充权限: ${role.name}`, {
                permissions: role.permissions.map(p => p.code)
              });
            }
          }
        }
      }

      // 记录用户和角色信息到日志
      const userPermissions = user.roles?.flatMap(r => r.permissions?.map(p => p.code) || []).concat(user['_permissions'] || []);
      
      logAuth(`用户验证成功: ${user.username} (${user.id})`, {
        roles: user.roles?.map(r => r.name),
        permissions: userPermissions
      });

      return user;
    } catch (error) {
      logAuth(`JWT验证失败: ${error.message}`, { 
        username: payload.username,
        userId: payload.sub 
      });
      throw error;
    }
  }
} 